#ifndef SKYNET_H
#define SKYNET_H

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <memory.h>
#include <time.h>
#include <sys/time.h>
#include <fstream>
#include <cstring>
#include "ap_int.h"

#ifdef __SDSCC__
#include "sds_lib.h"
#else
#define sds_alloc malloc
#endif
#define __APINT__
#ifdef __APINT__
typedef int DT;
typedef ap_int<8> ADT;
typedef ap_int<19> BDT;
typedef ap_int<6> WDT;
typedef ap_int<19> MDT;
typedef ap_int<256> ADT32;
typedef ap_int<256> WDT32;
typedef ap_int<256> BDT8;
typedef ap_int<512> BDT16;

#else
typedef int DT;
typedef char ADT;
typedef int BDT;
typedef char WDT;
typedef int MDT;
struct DT32{DT data[32];};
struct ADT32{ADT data[32];};
struct BDT32{BDT data[32];};
struct MDT32{MDT data[32];};
struct WDT32{WDT data[32];};
struct BDT16{BDT data[16];};
struct BDT8{BDT data[8];};
struct MDT16{BDT data[16];};
#endif

#define na 8
#define nw 6
#define nb 16
#define nm 17

typedef int DT;


#define amin -128
#define amax 127

#define smin -262144
#define smax 262143

#define layer_count 19
#define check_scale 0.00001

struct layer
{
	char name[10];
	int iw, ih, ic, ow, oh, oc;
	int k, s, p;
};
#define conv0_offset  0
#define pool1_offset  207689
#define pool2_offset  312987
#define conv5_offset  353574
#define conv6_offset  394161
#define pool3_offset  475335
#define conv7_offset  496749
#define conv8_offset  539577
#define conv9_offset  582405
#define conv10_offset 625233
#define conv11_offset 682337
#define conv12_offset 825097
#define conv13_offset 835804
#define fm_all        842942

#define conv1_b 13792
#define conv2_b 13800
#define conv3_b 13816
#define conv4_b 13832
#define conv5_b 13856
#define conv6_b 13880
#define conv7_b 13928
#define conv8_b 13976
#define conv9_b 14072
#define conv10_b 14168
#define conv11_b 14296
#define conv12_b 14616
#define conv1_m 13796
#define conv2_m 13808
#define conv3_m 13824
#define conv4_m 13844
#define conv5_m 13868
#define conv6_m 13904
#define conv7_m 13952
#define conv8_m 14024
#define conv9_m 14120
#define conv10_m 14232
#define conv11_m 14456
#define conv12_m 14628

#define conv1_w 0
#define conv2_w 9
#define conv3_w 73
#define conv4_w 91
#define conv5_w 283
#define conv6_w 310
#define conv7_w 886
#define conv8_w 940
#define conv9_w 3244
#define conv10_w 3352
#define conv11_w 9496
#define conv12_w 9856
#define conv13_w 13696

/**********utils.cpp************/
void load_fm(ADT* fm, layer l);
void load_parameter(WDT32* parameter, int length);
void load_weight(WDT32 *weight, int length);
void load_biasm(BDT8* biasm , int length);
void check(ADT* result, ADT* golden, int len, layer l);
void check_fm(ADT* fm, layer l);
void check_bbox(BDT* bbox, layer l);
void show_fm(ADT* fm, layer l);

void generate_fm(DT* fm, layer l);
void generate_weight(DT* weight, layer l);

/**********transform.cpp************/
void stitch(ADT* ifm[4], ADT* ofm, layer l);
void distitch(ADT* ifm, ADT* ofm[4], layer l);
void fm_DT_2_DT32(ADT* in, ADT32* out, layer l);
void fm_DT32_2_DT(ADT32* in, ADT* out, layer l);
void distitch_bbox(BDT* ifm, BDT* ofm[4], layer l);
void bbox_DT16_2_DT(BDT16* in, BDT* out, layer l);
void bbox_DT8_2_DT(BDT8* in, BDT* out, layer l);

/**********PWCONV.cpp [HW]************/
void PWCONV1X1_PL(
    const ADT IFM[32][43][83],
    BDT OFM[32][43][83],
    const WDT WBUF1x1[32][32],
    bool clear_enable = false
#ifdef USE_DSP
    ,
    bool ap_clk_div2
#endif
);
/**********DWCONV.cpp [HW]************/
void DWCONV3X3_PL(const ADT IFM[32][43][83], BDT OFM[32][43][83], const WDT WBUF3x3[32][3][3]);

/**********SkyNet.h [HW]************/
void SkyNet(ADT32* fm, WDT32* weight);
#endif
